Document Windows, Tool Windows, Auxiliary Windows 5
Installation 7
Files 7
Folders 7
The Text Subsystem 8
Creating, Opening, Closing, Saving, and Printing Text Documents 8
Basic Editing 8
Navigation Keys 9
Drag & Drop 9
Drag & Pick 9
Text Views as Containers 9
Text Setting 11
Text Rulers 11
Finding and Replacing 12
Export as Ascii 12
The Development Subsystem 13
Compiling Oberon Modules 13
Browsing Tools 14
Loading and Unloading Modules 14
Executing Commands 14
Debugging 15
The Forms Subsystem 17
Control Properties Inspector 17
Menu Configuration 18
String Resources 21
Subsystems and Global Modules 22
Distribution 24
How to Develop Oberon/F Components 25
Standard Commands 27
File Menu 27
Edit Menu 28
Font Menu 29
Attributes Menu 29
Windows Menu 31
Custom Commands 32
Controls 32
DevAlienTool 32
DevBrowser 33
DevCmds 33
DevCommanders 33
DevCompiler 34
DevDebug 34
DevMarkers 35
DevInspector 35
FormCmds 35
HostCmds 36
StdClocks 37
StdControlCmds 37
StdMenuTool 38
StdStamps 38
TextCmds 38
TextRulers 40
Introduction
This document serves as a user's guide for Oberon/F programmers. It is not intended as a manual for the end user of software written in Oberon/F. Knowledge of the Macintosh user interface guidelines is assumed.
With Oberon/F, there are no separate environments for developing programs, for testing and debugging programs, or for the the distribution of programs. Instead there is only one, truly integrated, environment for all these purposes. A distribution version of an Oberon application is created simply by stripping away all tools which are specific to the development process (see section "Distribution" in this documentation).
Development tools must not be distributed. However, all other parts of Oberon/F may be freely distributed along with applications, without royalties or other fees.
Such a customized Oberon/F environment always has the basic capabilities of Oberon/F's compound document architecture, and of the standard text and forms subsystems. Furthermore, it constitutes a standard Macintosh application, where the (boot) application can be double-clicked, where documents can be dropped onto the application icon to open them, etc.
"Native" applications which are only developed under, but not based on, Oberon/F can be developed as well. For this purpose, a linker tool is provided. Normally, Oberon modules are linked and loaded dynamically, such that a separate linker is not strictly necessary. However, it is possible even for pure Oberon/F applications to link all or some of their modules together, in order to reduce the number of files to distribute. For further information about this topic, refer to the document "Oberon/F, Macintosh, Platform-Specific Issues".
When working in the Oberon/F environment for the first time, the following may be helpful to remember: Almost all modifications to Oberon/F documents are undoable, making it quite safe to try out a feature. In general, multi
level undo/redo is available, i.e. not only one, but several commands can be undone (as many as memory permits).
Whenever the system is working on the completion of some command for more than a fraction of a second, Oberon/F changes the cursor to a special busy cursor sequence. However, this does not guarantee that the executing program does make any progress. For example, the busy cursor will keep advancing, even if the program entered an endless loop. Use command-option-. to terminate such a program (note that it may take a few seconds before you see a reaction).
Document Windows, Tool Windows, Auxiliary Windows
There are three kinds of windows in Oberon/F: document windows, tool windows, and auxiliary windows. A document window may contain e.g. a text or a form layout, or your custom view object type. When the contents of a document window has been modified (made "dirty") and the user tries to close the window (or quit the application), the system asks the user whether the document should be saved.
A tool window allows to invoke actions on some document window underneath it, typically such a tool is a modeless dialog. Tool windows look the same way as any modeless dialog on the Macintosh, i.e. the same way as a document. In order to avoid confusion, the titles of tool windows are put in "<<" and ">>" brackets.
Auxiliary windows are used mainly to hold temporary data for information purposes, e.g. the output of a browser. The contents of an auxiliary window may be editable, but the system doesn't ask whether a modified auxiliary window should be stored, i.e. it is temporary in nature. The Log window (which is not available for application distribution) is an example of such an auxiliary window. Auxiliary windows can be recognized by their "[" and "]" brackets around their titles.
The contents of any Oberon/F window can be viewed in several other windows simultaneously (using the New
Window command in the Windows menu). In contrast to their primary window, all additional windows created in this way can be recognized by the "(" and ")" brackets around their titles, regardless of whether they are document, tool, or auxiliary windows.
If the primary window is not a document window, the system doesn't ask whether its contents should be saved upon closing, even if its contents had been modified in some way.
Document and auxiliary windows may have scroll bars. A window with scroll bars is resizable; note however that resizing a window only changes how much of its contents are visible, but never changes the contents (e.g. how text is set) itself.
Installation
Start the Oberon
installer application on disk number 1. The installer will lead you through the installation procedure.
Oberon/F requires a Macintosh with a MC68020 or better, with Mac OS 7.0 or higher, and a floating point unit (FPU) or FPU emulator. If you don't have an FPU please read the Read
Me (SoftFPU) file in the Oberon folder.
The resulting Oberon folder contains several files and folders:
Files
Oberon/F The completely linked Oberon/F application.
Oberon/X A partially linked Oberon/F application.
Demo A demonstration text.
Read Me Release notes and copyright notice.
Read Me (SoftFPU) Information about a third-party floating-point emulator.
Welcome This text is used as input by some of the tutorial examples.
Folders
Code This folder is empty. After the compilation of a global module, its code file is
placed here.
Dev This folder contains the resources of the development subsystem. The
subsystem's code is linked into Oberon/F (not into Oberon/X) and not available
as separate code files.
Docu This folder is empty. Documentation for global modules can be placed here.
Form This folder contains the forms subsystem with the visual designer.
Host This folder contains private code of Oberon/F.
Mac This folder contains interface modules for direct Toolbox and Mac OS access.
Manuals This folder contains on-line documentation not specific to a particular module or
subsystem.
Omosi This folder contains an example view class.
Omosi Docs This folder contains documents created with Omosi views.
Rsrc This folder is empty. Resources (dialogs, strings) for global modules may be put
here.
Samples This folder contains the example files of "Oberon/F, Framework, Quick Start and
Quick Reference".
Std This folder contains private code of Oberon/F.
Sym This folder is empty. After the compilation of a global module, its symbol file is
placed here.
System This folder contains the core of Oberon/F.
Text This folder contains the text subsystem, with the standard document/program
editor.
Tutorial This folder is empty. If the tutorial examples are compiled, their symbol / code
files are placed here.
The Text Subsystem
The text system is intended to support tasks of program writing and documentation, but also provides basic abstractions that can be used by every application which needs editable texts. For this reason, the text system is part of the standard configuration of Oberon/F.
It is currently not intended to cover all subtle features of a standard word processing application. However, the system can be used for many tasks that would usually ask for a word processor. Furthermore, the unique extensibility of Oberon allows for customization and extension of the text system with few principal limitations.
The following covers the user interface of the text system, not its application programming interface. For an introduction to the programming interface consult the manual "Oberon/F, Framework, Tutorial and Reference" or "Oberon/F, Framework, Quick Start and Quick Reference".
Creating, Opening, Closing, Saving, and Printing Text Documents
As for other applications, the File menu is used for these purposes. By convention, document names on the Macintosh contain no extension such as ".Mod" or ".ODC".
To open a document use Open... from menu File. When holding down the option
key before selecting Open..., arbitrary files can be opened. If such a file is not an Oberon/F document, it will be converted if a converter is available. Currently, converters for Macintosh TEXT, Macintosh PICT, and ETH Oberon V2 and V4 text files are installed. If the file is not of any such type, it is interpreted as plain ASCII text.
To create a new document, the command New (menu File) can be used. It opens a window containing an editable text. Custom menu commands may allow to open windows with other contents than text. For an introduction on how to edit the menu configuration see section "Menus" further below.
Basic Editing
Oberon/F text views either display a selection or an insertion point (the caret). Text stretches are selected by clicking at one end of the stretch and then moving the cursor over the stretch to the other end. Words may be selected by double
clicking them. Double clicking outside of a text view to the left or right of a line can be used to select whole lines. (This does not work for embedded text views.) Also, an existing selection may be extended or reduced by holding down the shift
key when clicking. Typed text appears at the insertion point if there is any, otherwise it replaces the selection. The delete key either clears the selected text, or deletes the character to the left of the insertion point.
The attributes of selected text can be modified using the Font and Attributes menus. In addition to these system attributes, texts also support vertical offsets of individual characters. These can be manipulated using the commands Superscript and Subscript from menu Text.
Sometimes it is useful to view two or more portions of the same text simultaneously, e.g. to make a large selection by setting the caret in one view to the start of the stretch to be selected and then shift
clicking at the end of that stretch in the other view. New
Window in menu Windows can be used to obtain an additional view onto the current front window. Open
Window is similar except for opening a view onto a part of the current front window, the so-called focus view.
Navigation Keys
Arrow keys can be used to move the insertion point to the left, right, upwards, or downwards. If the option-key is pressed before the left/right arrow key, the insertion point is moved by word, not by character. If the option-key is pressed before the up/down arrow key, the insertion point is moved by paragraph, not by line. If the shift-key is pressed before an arrow key, the current selection (or insertion point) is extended or shrinked. Both modifier keys may be used together as well. The navigation keys on the extended keyboards (Page up/down, Home, End) may be used to scroll by one page at the time, or to the beginning/end of a document.
Drag & Drop
When clicking into an already selected text stretch without moving the cursor out of that selection, the selection is removed and the insertion point set instead. However, by moving the cursor out of the text selection while still holding down the mouse button, the selected text stretch is dragged to another place. When releasing the mouse button over a suitable position, the selected stretch is dropped. (If the target position is not able to consume a text stretch, e.g. in a window's scrollbar, nothing happens.) By dragging a piece of text and dropping it to a new place, the text piece is moved to the new place. By holding down the option
key while dragging, the dropped piece is a copy of the dragged one: A copy of the selected piece is inserted at the new place. When crossing document boundaries the dragged object is always copied, regardless of whether the option
key is held down or not.
If you move the cursor over a partially obscured window while dragging, the window comes to the top when you don't move the cursor for a second or two. When dropping, the window containing the drop destination comes to the top, if it isn't there already.
Drag & drop currently works within Oberon/F only, not with the Finder or other applications.
Drag & Pick
A novel feature of Oberon/F is the capability to drag a selected object to another place in order to pick up attributes. The text system uses this facility to support setting the text attributes of a selected piece of text to those used by any other visible text stretch. To drag & pick, hold down the control
key while dragging. Like drag & drop, drag & pick also works across windows. During dragging, obscured windows come to the top in a similar way as with drag & drop. However, after picking always the source window comes to the top again; not the destination as with drag & drop.
Text Views as Containers
A text may contain arbitrary Oberon/F views, directly floating in the stream of characters. For example, the current date and time is displayed by a standard clock view:
Not only simple and small views like the above clock may float in a text; any view is possible. A few lines below you can see a text view embedded in this text; the embedded text view itself contains two other text views. To see where there are embedded views in a window, you can click in the window's title bar while holding down the option
A container view is a view which may contain arbitrary other views, text views are examples of container views. A container view contains intrinsic contents (in this case, text pieces), and views. Both intrinsic contents and views may be selected, e.g. if you are reading this text on-line, you may select all its contents, including all the text and the various views floating in it (try Select
All in the Edit menu). However, at times you may want to select exactly one view, which is then called a singleton. Singletons show in a distinguished way that they are selected: with an outline around the view, and with handles if the view is resizable.
The view which contains the current selection, or the caret, is called the current focus. Except the outermost view, the focus and all the views in which it is contained show focus borders: two dotted outlines around a view. Note that a focus is not a selection, rather it may contain the selection. However, a focus can be turned into a singleton by clicking into its focus border.
If several views are nested, the user can focus the innermost simply by clicking into it. This mechanism of directly clicking into the contents of an embedded view is called trans
clicking. It is especially handy when dealing with views nested several levels deep:
Of course, sometimes it is necessary to edit the text surrounding an embedded view. For example, selecting the embedded view itself, instead of selecting something inside the embedded view, makes it necessary to disable trans
clicks. This can be done by holding down the command
key when clicking. To select the outermost text view embedded in a document, use the command Select
Document in menu Edit. Note that this is different from Select
All, which merely selects the focus' contents. In a container, the focusing of one of its embedded views can be prevented altogether, using the Prevent
Subfocus command in the Dev menu. This can be convenient in a graphical container which is meant for layout editing, e.g. in the forms editor used for dialog layouts.
An embedded view can be resized, if it allows this. To resize such a view, it needs to be selected first, as a singleton. Once it is selected, graphical handles appear that can be dragged to interactively resize the view. The view may enforce constraints on legal sizes - this is immediately visible while resizing the view. By holding down the shift
key when resizing, two opposite handles can be dragged simultaneously, effectively turning the resize into a move in the area of the containing view. (For some containers, such as text, free moving does not make sense. In this case the move operation will have no visible effect.)
To scroll an embedded (focused) view, hold down the option
key when the cursor is over a scroll bar.
Note that the clipboard supports two different paste operations, represented by Paste and Paste
Object in the Edit menu. While Paste tries to merge the clipped model (the data structure displayed by the view in the clipboard) into the destination, Paste
Object always pastes the entire view, creating an embedded view. Paste succeeds in merging clipped and destination model, if both are of the same kind. (For example, a text stretch copied into the clipboard is actually carried by a text view held by the clipboard. When pasting into another text, the text view in the clipboard is ignored and the clipped text is directly inserted into the destination text.) If on the other hand the models of clipboard and focus are incompatible, Paste operates the same way as Paste
Object. In addition to Paste
Object, the command Paste
Window can be used to open a new document containing a copy of the view currently held by the clipboard.
Drag & drop always follows the semantics of Paste, i.e. it tries to merge the dragged object into the drop target. (This is the common case when moving model pieces around within a view.) In order to avoid merging of objects, the clipboard can be used: Cut and Paste
Object or Copy and Paste
Object to replace drag & drop.
Text Setting
A text may contain plain characters, embedded views, and various control characters. Control characters and text
aware views affect the way a text stretch is set into a text view: a TAB (inserted using the tab key) forces the next word to the next tab stop, a LINE (inserted using the return or enter key) ends a line and continues setting on the next, a PARA (inserted using command New
Paragraph from menu Text) ends a line and also a paragraph, causing begin
of-paragraph formats to be applied to the next line. If a TAB is entered in a text for which there is no tab stop to the right of the caret, the TAB acts as a fixed-width space.
TABs at the beginning of a line can be used to control the indentation of structured text, such as programs. After a LINE is entered and the previous line has started with TABs, the new line will start with the same number of tabs (auto indentation). The commands Shift
Left and Shift
Right (menu Text) modify the indentation of a selected range of lines. Note that these indentation aids only work if you use TABs for indentation, but not spaces.
Special hyphens can be used to control the breaking of words. A standard hyphen, such as in Standard
Hyphen (inserted using option
-) allows for word breaking, just as a soft
hypen (inserted using command Insert
Hyphen from menu Text) does. While standard hyphens are always visible, soft
hyphens are only displayed when actually activated to break a word at the end of a line. Non
breaking hyphens as in "Non
Breaking
Hyphen" (inserted using command Insert
Hyphen from menu Text) prevent breaking a word after the hyphen. Non
breaking spaces (inserted using option
space) prevent breaking words and must be used for spaces which should be underlined. A digit space is the same as a non-breaking space but with a width equal to the digit "0" of the same font. If you use a font with monospaced digits, you can use digit spaces to right-adjust numbers (command Insert
Digit
Space in menu Text).
Text Rulers
The most prominent text
aware views that affect text setting are TextRulers. Every text view provides an invisible default ruler that controls the setting of text in the absence of normal rulers. A new ruler can be inserted using command Insert
Ruler from menu Text. Rulers and PARA characters are usually invisible; the command Show
Marks / Hide
Marks (menu Text) can be used to make both visible.
Note that the setting of a paragraph (right margin, etc.) is only determined by its ruler (the default ruler, if there is no other), and not by the text view's size.
A ruler has two active (clickable) areas: an icon bar at the top, and a tab stop and margin marking bar at the bottom. A passive scale is displayed in the middle. The leftmost icon allows resetting the first line indentation, left, and right margins to values within the range of the currently visible view part. This is especially useful when dealing with embedded text views of limited size. At the left end are three icons to adjust the line grid, where clicking the left icon decrements and clicking the right icon increments the line grid. Between these two icons the actual line grid setting is shown in points; a value of 1 signals that the line grid has been disabled. This icon can be selected to set the line grid directly using the size entries in the Attributes menu. By default, the line grid is disabled (set to 1).
Note that enabling a line grid can have unexpected results, especially if you successively increment or decrement it by clicking on the line grid icons. Since lines are always forced to lie on the grid, small changes of the line grid or of the font size may force a line to jump one whole line up or down.
The next four icons allow to set the formatting mode. Possible modes are: flush left, centered, flush right, and fully justified. The current mode's icon is high
lighted. The next icon triple allows adjustment of the lead space inserted before every paragraph. Note that new paragraphs are begun by inserting either a ruler or a PARA character. A plain LINE character (inserted using the return key) does not begin a new paragraph! Finally, the last icon can be used to force a page break just before the ruler when printing.
The tab stop and margin marking bar supports direct manipulation of its components. Two half
triangles at the left end are used to control the indentation of the first line of every paragraph and the left margin. A triangle at the right end controls the right margin. Small up
pointing triangles show positions of tabulator stops. New tab stops can be set by clicking into empty areas of the marking bar; old tab stops can be removed by dragging them out of the ruler. Single tab stops can be moved by dragging them; all tabs stops to the right of and including the dragged one can be moved by holding down the option
key while dragging.
If you want to change the invisible default ruler, insert a new ruler, then set it up as you like, select the whole ruler, and then execute Make
Default
Ruler in menu Text. Similarly, if you want to change the default attributes (font, etc.) of a text, type some text, set its attributes to the desired values, and then execute Make
Default
Attributes in the Text menu. In this way, you can prepare (possibly empty) template texts (stationaries) with suitable formatting and attributes as defaults.
Finding and Replacing
The menu entries Find
Replace... and Find
Again from the menu Text can be used to open dialogs that support finding and replacing text pieces, and for repeated finding, respectively. Text may be found in a case sensitive or insensitive way (check box ignore
case), and the search pattern may be restricted to only match word beginnings, word endings, or both (check boxes word
begins
with and word
with). The latter case limits the search to word matches.
All replacing actions, including Replace
All, which replaces all matching fragments from the current position to the end of the text, can be undone. The replacement always adopts the text attributes of the (first character of the) replaced fragment.
Again searches for the currently selected string, starting from the end of the selection. If there is only a caret, it searches for the previously used string starting at the caret position. Thus Find
Again can be applied even without ever using the Find
Replace... dialog.
If a string is not found from the current position to the end of the text, a beep sound is emitted. If the same operation is executed again, the search is started at the beginning of the text.
Export as Ascii
The text contained in the focus text view can be translated and saved into a Macintosh Ascii format file, with type "TEXT" and creator "obnF". Use command Export
Ascii... in the Text menu.
The Development Subsystem
Compiling Oberon Modules
Besides consuming stored text documents, the Oberon compiler can compile modules from anywhere in any displayed text document. If the beginning of a diplayed text is also the beginning of a module, the command Compile in the menu Dev can be used to compile the module. If the module begins somewhere in the middle of a displayed text, its beginning can be selected, e.g. by double
clicking on the keyword MODULE, and then the command Compile
Selection in the menu Dev can be used.
To compile a list of modules at once, a list of module names needs to appear in some displayed text, e.g.
FormModels FormViews FormControllers FormCmds
By selecting the part of the list that should be considered by the compiler and by invoking the command Compile
Module
List from menu Dev, the listed modules are compiled consecutively. The process stops as soon as an erroneous module has been encountered. The compiler reports on the success or failure of compilations by writing into the system log. The log is a special text displayed in an auxiliary window. It can be opened using Open
Log and cleared using Clear
Log, both from menu Info.
The log is a development tool, i.e. it should be used for debugging purposes and for development tools only. End-user applications are not expected to display a log. Whether or not a log window is opened upon startup of Oberon/F is determined by the configuration's Config module (in folder "System:Mod"). This module can be changed by the programmer as desired; by default it only contains one statement, which opens the log.
Module
List is a convenient command in menu Dev, which opens the module sources of one or several modules: select a module name, e.g. Config, and then execute Open
Module
List. This command can save you much time when you work with multiple subsystems (-> Subsystems and Global Modules) at the same time.
When compiling a newly created or a modified module, direct compilation of the displayed program text is recommended. In addition to writing to the system log, the compiler then also inserts error markers into the source text and places the caret after the first marker. Each marker represents an error flagged by the compiler in the source text. Normally, a marker is displayed as a crossed
out box. However, simply by clicking into it, a marker expands to display the corresponding error message. If the insertion point is directly behind a marker, it can be expanded via the command Toggle
Error
Mark from the Dev menu (or more likely via its keyboard equivalent).
The command Next
Error (menu Dev) can be used to skip forward to the next marker. Unmark
Errors removes all remaining markers from a text. However, the latter is rarely required: The compiler automatically removes all old markers when re
compiling a text; and when storing a text, contained markers are filtered out, i.e. do not appear anymore when the text is re-opened.
If a compiled module contains one or several errors, the text is scrolled to the first one. If this doesn't happen, the module was successfully compiled. In addition to this feedback, the compiler writes the number of errors found to the log, if there are errors. If the module interface has changed compared to a previous version, the changes are listed in the log as well.
The successful compilation of a module yields two files: a symbol file and a code file. A symbol file contains the information about a module's interface, and is used by the compiler to check imported modules for consistency. The code file represents the generated code (Motorola 68020 code on the Macintosh). The contents of a code file is linked and loaded dynamically when needed, thus there is no need for a linker.
Symbol files are only needed during development (used by the compiler and the interface browser), they are not needed to run modules. A symbol file is a special encoding of a module's interface, i.e. of its exported constants, variables, types, and procedures. If the interface of a module is changed and the module recompiled, a new symbol file is written to disk. When compiling a module, the compiler reads the symbol files of all modules imported. This information is used to generate code, but also to type-check the correct use of imported identifiers. After the interface of a module has been modified, all modules importing it (i.e. all its clients) must be recompiled. Only those modules need to be recompiled which actually use the feature which has been changed. A mere addition of features does not invalidate the clients of a module: if you export a further procedure, for example, no clients need to be recompiled. This also holds for constants, variables, and types, but not for type-bound procedures. The latter is considered not an extension, but rather as a modification of an interface, and thus may invalidate clients.
Code files are produced, but never read during development. They are necessary to run modules, i.e. the dynamic (linking) loader must be able to read them.
Browsing Tools
A common cause of compile
time errors is the wrong use of interfaces. To quickly retrieve the actual definitions of items exported by modules, the browser may be used. The interface of a whole module is displayed when selecting the name of a module and executing Interface from menu Info. To display the definition of an individual item, e.g. a type or procedure, the qualified name of that item, i.e. "module.item" should be selected with the same command. The browser displays its output in a form that can directly be used as input for further browsing actions.
Two related commands, Source and Documentation from menu Info, allow to look up an item's definition in a source file, or in an on-line documentation, respectively. They also work both on selected module names as well as on names in the form "module.item".
Loading and Unloading Modules
Once a module passes the compiler it can be loaded into the system and used. The list of all currently loaded modules is displayed by Loaded
Modules (menu Info). In order to use a new version of a module that is already loaded, the module needs to be unloaded first. Command Unload (menu Dev) takes a focused module source as input and tries to unload the corresponding module. Unload fails if the module is still in use, i.e. if it is imported by at least one other module that is still loaded. (In general, modules can only be released top down.) The command Unload
Module
List takes a selection as input, which must consist of a sequence of module names.
Executing Commands
There are several ways to execute commands (i.e. parameterless procedures exported by Oberon modules) within Oberon/F. A command name can be written into a text, as a string of the form "module.procedure", selected, and executed using Execute in menu Dev. An easier way is to precede the command name with a commander: menu Dev provides an entry Insert
Commander. Clicking on a commander interprets the string following it as a sequence of commands, e.g.
"Dialog.Beep; DevDebug.ShowLoadedTopModules"
If the string consists of only one command, the string delimiters may be omitted, e.g.
Dialog.Beep
With such simple commands, it is possible to combine the unloading of an old version with the execution of a new version of a command (resp. of its module): option-click on the commander causes the command's module to be unloaded, and then the new module version is loaded and the procedure executed. Note that this only works for top-level modules, i.e. for modules which are not imported by any other modules.
Debugging
When a run-time error occurs, e.g. a division by zero or some assertion trap, a trap window is opened. Such a window contains a text which shows the stack contents at the time when the trap occurred. An extract of such a trap text is shown below:
In the first line, the trap number is given, e.g. TRAP 0. Further below, a sequence of procedure activations is given, e.g. the last active procedure (where the trap occurred) was Demo.Trap, which had been called by StdInterpreter.CallProc, which had been called by StdInterpreter.Command, etc. Each procedure is marked with a small diamond mark to the left of its name. Clicking on this diamond mark produces a new window which shows the global variables of the module in which this procedure is defined, e.g.
The diamond mark to the right of a procedure opens the source of the module in which this procedure is defined, selects the statement which has been interrupted, and scrolls to this selection.
But now let us go back to the stack display. The lines below a procedure's name show the parameters and local variables of the procedure, sorted alphabetically. The following example
pn Kernel.Name "Trap"
means that a local variable pn of type Kernel.Name had the value "Trap" when the trap occurred. After a pointer variable, a diamond mark allows to follow the pointer to the record to which it points, e.g. the pointer i
i StdDialog.Item [0043F08CH]
can be followed (by clicking on the diamond mark) to the record
Such a display is opened in another window. The fields of a record are indicated by the preceding ".". On the first line, the path you have followed is indicated. If you have followed more than one dereferencing step, a diamond mark at the right end of this line lets you trace back again step by step.
It should be noted that at no time during debugging the normal Oberon/F environment is left, there is no special "debugging mode" or "debugging environment"; everything is integrated instead!
It is typical for object-oriented programs that their control flows can become extremely convoluted and hard to follow. Thus following a program statement for statement (single step), by message sends, or by procedure calls in practice turns out to be unpractical for debugging large systems. Instead, Oberon/F uses a more effective debugging strategy:
Let errors become manifest as soon as possible.
Instead of waiting for some error to occur, and then trying to find one's way backward to the cause of the error, we attempted to flag errors as closely to their cause as possible. This is the only way to truly save debugging time. The language implementation follows the same strategy, by checking index overflows when accessing arrays, by checking NIL accesses when dereferencing a pointer, etc. In addition to these built-in checks, Oberon/L provides the standard procedure ASSERT, which allows to test for an arbitrary condition. If the condition is violated, a trap window is opened. Oberon/F procedures consequently use assertions e.g. at the beginning of a procedure to check whether its input is valid. This prevents that a procedure with illegal input may perform any damage to the rest of the system.
This stategy has proven itself again and again during the development of Oberon/F, and is strongly recommended for serious development work.
The Forms Subsystem
The command New
Form... in menu Dev creates dialogs and other forms that match exported global variables. It is important to notice that the created form is non
modal. Almost all dialogs in Oberon/F are non
modal, as long as the conventions for the underlying platform permit.
To get started, enter "TextCmds.find" into the link field of the New
Form dialog. By clicking the Create button, a dialog is automatically created which has fields find and replace, and buttons like FindNext and ReplaceAll. These fields and buttons directly match the record fields of variable find in module TextCmds. To verify this, select the string "TextCmds.find" , and execute command Interface in menu Dev. The browser will display the definition of the record type.
The dialog created by New
Form... exhibits a simple default arrangement of control elements, shown as an editable layout. The elements of such a layout may be re-arranged, renamed, or otherwise modified using the menus Layout and Controls. These menus appear automatically whenever a form is focused.
To see a form layout also as a fully operational dialog, execute Open
Dialog
(Tool).
The size of a form view can be adjusted by selecting the whole document (Select
Document in menu Edit) and then dragging the graphical handles.
An edited dialog can be saved by saving the window of the form layout. Oberon/F saves dialogs in the standard document format. By convention, Oberon/F forms are saved in files with names of the form "variable", in the appropriate "Rsrc" folder (-> Subsystems and Global Modules). For example, the standard "Find & Replace" dialog is stored in ":Text:Rsrc:find". A form can be opened either by opening it as a document (for layout editing), or by adding an item to one of the menus (for opening it as a dialog). Further below, examples of such menu items will be shown.
Note that forms are saved in their editable state; only when they are opened via menu commands (using the pseudo commands OpenAuxDialog or OpenToolDialog, -> Menu Configuration) are they opened as auxiliary or tool dialogs. The difference between auxiliary and tool dialogs is that auxiliary dialogs are self-contained, e.g. dialogs to set up configuration parameters or data entry masks. Tool dialogs operate on windows below them, e.g. the Find
Replace dialog.
Control Properties Inspector
The inspector is a tool used to inspect and to modify the properties of standard controls. Standard controls are push buttons, check boxes, radio buttons, fields, and captions. A field represents editable text, while a caption represents non-editable ("static") text. Usually, there is a caption for every field, but there may also be captions without fields. All controls are special views. As every view, any control can be inserted into any container, be it a text, a spreadsheet, or whatever other container is available. However, most controls are put into forms.
Each control can be linked to a variable, more exactly to the field of a globally declared record variable. When the control is allocated, Oberon/F tries to link the control to its variable, using the advanced metaprogramming capabilities of the Oberon/F kernel. In this way, the link between control and variable can be built up automatically when a dialog is created or loaded, and correct linking (i.e. correct typing) can be guaranteed even after a dialog layout had been edited.
Controls may take on different states at run-time. Depending on the control and on the underlying user interface, these states may be represented in visually distinct ways:
enabled/disabled only enabled controls may be modified interactively
To disable a control, its guard should call Dialog.Disable.
Controls which cannot be linked to their variable are always disabled.
defined/undefined illegal or otherwise undefined values may be hilighted as such
To mark a control as undefined, its guard should set Dialog.par.undef.
normal/readOnly controls (e.g. fields) may be denoted as read-only, i.e. under program
control only.
To mark a control as readOnly, its guard should set Dialog.par.readOnly.
Controls which are linked to read-only variables are always readOnly.
Note that the above states are determined wholly at run-time, they are never externalized or internalized.
All controls have the following properties, which are externalized when the controls are written to files:
link this is the name of a global variable, to which the control is linked, e.g.
TextCmds.find.replace.
label this is the displayed string (not applicable to fields).
guard this optional command is a guard which allows to disable/enable a control
selectively.
element controls may be grouped. A control with the element property set belongs the the
group of its closest non-element predecessor. On the Macintosh, this property is
not interpreted.
light font a field may either be displayed in the standard font for this purpose, or in a more
discreet ("light") font. On the Macintosh, this property is only interpreted in fields
and captions.
Additional push button properties:
default the button is activated when the user presses return or enter.
cancel the button is activated when the user presses escape.
Instead of linking a push button to a variable, it can be linked to a command also, e.g. by setting link to Dialog.Beep.
Additional check box properties: none
Additional radio button properties:
level a radio button is "on" when the value of the variable bound to the button is equal
to level.
Additional field properties: none
Additional caption properties: none
Menu Configuration
The configurable menus can be inspected using Menus from menu Info. The displayed text can be edited, and the current menu configuration updated accordingly (Update
Menus in menu Info). To make changes to the menus permanent, the menu text must be saved to disk. The file System:Rsrc:menus contains the startup menu configuration, i.e. the text which is opened when Menus is executed.
The menu text consists of a sequence of menu definitions, which themselves consist of sequences of menu items. An example is the following extract of the Dev menu definition:
Each menu has a name, in this case it is Dev. Optionally, the module name can be followed by a menu type, e.g.
MENU "Text" ("TextViews.ViewDesc")
A typed menu is only installed in the menu bar as long as the current focus has a matching type. The other menus are always available. Standard menus,i.e. File, Edit, Font, Attributes, and Windows are predefined and not part of a menu configuration text.
There are two kinds of menu items: normal items and separators. A separator optically organizes a menu into different groups of items. Normal menu items consist of four strings: a name, a keyboard shortcut, an action command, and a guard command. The name is the string presented to the user in the menu. The keyboard shortcut, which may be empty, allows to associate keyboard equivalents to the menu item. The action string contains the command sequence which is activated when the menu item is executed. The guard string, which may be empty, contains a command sequence which is called to determine whether the item is currently enabled or disabled, checked or unchecked, or to set up a current item name which overrides the normal name (e.g. to toggle between Show
XYZ and Hide
XYZ).
Command strings such as the action or guard strings may contain a sequence of calls to parameterless exported Oberon procedures, connected by semicolons. In the above example, the command
"DevCommanders.Deposit; PasteView"
calls procedure Deposit of module DevCommanders. Afterwards, the pseudo-command PasteView is executed. PasteView is known to the Oberon command interpreter: it fetches a view from a global queue, and pastes it to the focus. There is a convention in Oberon/F that for every concrete view type there is a corresponding Deposit procedure, which allocates such a view and then deposits it in a global view queue (by calling Views.Deposit).
The list of built-in pseudo-commands is the following:
PROCEDURE PasteView
Takes a deposited view from the global view queue and pastes it to the focus.
PROCEDURE Open
Takes a deposited view from the global view queue and opens it in a new window.
PROCEDURE OpenDoc (spec: ARRAY OF CHAR)
Takes a file specification of an Oberon/F document as parameter, and opens the document in a window. Parameter spec must be the path name of a file.
Example:
"OpenDoc('System:Rsrc:menus')"
PROCEDURE OpenAuxDialog (spec, name: ARRAY OF CHAR)
Takes a dialog file specification and a dialog name as parameters, and opens a dialog with the specified dialog. The dialog is opened as an auxiliary window. Parameter spec must have the form "module.variable", denoting the variable to which the dialog is bound.
Example:
"OpenAuxDialog('FormGen.new', 'New Form')"
PROCEDURE OpenToolDialog (spec, name: ARRAY OF CHAR)
Takes a dialog file specification and a dialog name as parameters, and opens a dialog with the specified dialog. The dialog is opened as a tool window. Parameter spec must have the form "module.variable", denoting the variable to which the dialog is bound.
A menu guard command tests whether its menu item should currently be disabled. If so, it calls Dialog.Disable. Several built-in guard commands are available:
PROCEDURE SelectionGuard
Disables menu item if there is no current selection.
PROCEDURE SingletonGuard
Disables menu item if there is no current selection, or if the selection doesn't encompass exactly one embedded view.
PROCEDURE CaretGuard
Disables menu item if there is no current caret, i.e. no selection of length 0.
PROCEDURE PasteGuard
Disables menu item if pasting is currently not possible.
PROCEDURE PasteCharGuard
Disables menu item if entering a character is currently not possible.
PROCEDURE PasteLCharGuard
Disables menu item if entering a long character is currently not possible.
PROCEDURE PasteViewGuard
Disables menu item if pasting a view is currently not possible.
PROCEDURE CopyGuard
Disables menu item if there is no selection, or if it cannot be copied.
PROCEDURE CutGuard
Disables menu item if there is no selection, or if it cannot be cut.
It is possible to execute code when Oberon/F is started up: upon start-up after having loaded and initialized its core, Oberon/F tries to load module Config. The module body may perform whatever configuration tasks deemed necessary. The standard Config module simply opens the Log window.
String Resources
String resources are files which define a mapping between strings, e.g. the string "untitled" may be mapped to "sans titre". This is useful to prevent hard-wiring textual messages in the program code, in order to make later editing of these messages possible without requiring a recompilation. From a programming point of view, string translation is done in several procedures of module Dialog, e.g. Dialog.MapString. String resource files can be normal Oberon/F text documents, which simply consist of the keyword STRINGS followed by a sequence of lines; each line contains a string (the key), a TAB, another string (to which the key is mapped), and a carriage return, e.g.
STRINGS
untitled sans titre
open ouvre
close ferme
Subsystems and Global Modules
A potential problem for any dynamically extensible system is the name space pollution problem of extensions: if two vendors would sell different extensions to Oberon/F, but under the same name, a conflict could arise: the two extensions could not be used on the same machine at the same time, since Oberon/F wouldn't know which was which.
It is possible to resolve such a conflict by appropriate renaming; however this requires that all clients of the renamed extension are updated accordingly; often an impossible task.
A better solution is to avoid conflicts right from the start, by giving extensions globally unique names. This can be done by providing a central registration service for all extensions, in this case for all Oberon/F modules. To reduce the administrative overhead of such a solution, Oberon microsystems opted for a two-level strategy: Oberon microsystems only registers subsystem names for a small fee, guaranteeing that such a name hasn't been registered yet. The buyer of a subsystem name should then guarantee that no two modules in this subsystem have the same name, where subsystem simply means a collection of modules. Typically, a subsystem also corresponds to a project.
This strategy is realized by a naming convention: every module name may contain a subsystem name as prefix, e.g. TextModels and TextViews belong to subsystem Text. The subsystem name begins with the first letter of the module name, and ends at the transition of a lower case letter (or digit) to an upper case letter. If no such transition exists, e.g. as in Files or Views, the module is called a global module, and belongs to the default subsystem called System. Global module names are reserved by Oberon microsystems. However, global module names may also be used by anyone for modules which are not meant to be published, i.e. where module name clashes can be resolved locally (e.g. when doing strictly in-house development and use of software) or where they are not critical (e.g. in a teaching environment).
This naming convention is technically supported by Oberon/F in that its compiler, linker, loader, and other development tools use subsystem names to determine where to fetch (or put) symbol files (or code files), as well as documentation and resource files. In the Oberon/F folder, there is one folder for every subsystem. The standard subsystems are Dev, Form, Host, Mac, Omosi, Samples, Std, System, and Text. The folder names must be identical to the subsystem names. A typical subsystem folder itself contains five folders: Code, Docu, Mod, Rsrc, and Sym.
- the Code folder contains the code files of all modules in the subsystem, one file per module
- the Docu folder may contain a programmer's reference for several or all modules in the subsystem, one file per module
- the Mod folder may contain the sources for several or all modules in the subsystem, one file per module
- the Rsrc folder may contain data files ("resources") for the whole subsystem, currently these are mostly strings files, one per subsystem; and possibly some files containing forms.
- the Sym folder contains the symbol files for several or all modules in the subsystem, one file per module
The Oberon compiler consumes program sources (usually the one displayed in the top window) and symbol files. A symbol file for module SubsystemModule is looked up as Subsystem:Sym:Module. The code file produced by the compiler is registered as Subsystem:Code:Module.
The browser (i.e. Interface) looks up a symbol file for SubsystemModule as Subsystem:Sym:Module.
The reference tool (i.e. Source and Documentation) look up as Subsystem:Mod:Module, and as Subsystem:Docu:Module, respectively.
Note that files are only looked up, but not searched: a file's location is strictly determined by the module name (including the subsystem prefix) and by the kind of file to be looked up. If the file isn't at the expected location, lookup fails; no further search is performed.
The only exception to this rule occurs with global modules. Their code files are always placed in the Code folder in the Oberon/F folder. Their symbol files are always placed in the Sym folder in the Oberon/F folder. However, if the lookup of either a code or a symbol file of a global module fails, another attempt is made to open the file in System:Code or System:Sym, respectively.
If one of the development tools tries to register a file (e.g. a symbol file) in a folder which doesn't exist, it places the file in the next existing folder further up in the folder hierarchy, i.e. possibly in the Oberon/F folder itself.
Distribution
If you develop add-on components (i.e. new subsystems) for Oberon/F, distribution simply means to distribute your subsystem folder(s). You may not want to distribute the source texts in order to protect your intellectual property rights, then you should delete them from the distribution version. You may not want to make one or several of your module interfaces public, or none at all if your application is not meant to be extensible. In this case, you should delete the symbol files in question. What you are distributing is exactly one subsystem folder.
On the other hand, if you want to distribute not only an add-on component but rather a whole stand-alone application for some reason, you should follow the steps outlined below:
1) Make a copy of your complete Oberon/F folder, which should contain the completely functional application. Perform the following steps only on this copy!
2) Delete the Dev folder. It is not permitted to distribute this folder or any part thereof.
3) Delete all the documentation and examples provided by Oberon microsystems, i.e. the Demo, Read
Me, and Welcome files, and the folders Manuals, Omosi, Omosi
Docs, Samples, Tutorials, Form:Docu, System:Docu, and Text:Docu.
4) Delete all source files (located in the various Mod folders) of modules whose
implementations you don't want to pulish.
5) Delete all symbol files (located in the various Sym folders) of modules whose interfaces you don't want to publish. This may or may not encompass the standard Oberon/F modules. If your application is not meant to be extensible, we recommend that you delete all symbol files.
Now you may continue on either of two possible paths. In the first case, which is more suited for extensible applications, you provide the unlinked code files of your application and of Oberon/F, together with a minimal linked application (Oberon/X) to boot the whole software system. In the second case, which may be more suited for closed applications, you link everything (your code files as well as the Oberon/F code) into one large application, and remove all symbol files.
Unlinked:
6) Delete the Oberon/F application. This application has the development system linked in. Therefore it is not permitted to distribute it!
7) Rename the Oberon/X application to whatever name is appropriate for your application.
8) Edit the About text in the System:Rsrc folder in an appropriate way.
9) Edit the menus text in the System:Rsrc folder in an appropriate way.
Linked:
6) Link your code files with the Oberon/F code files into a single application. See the documentation "Oberon/F, Macintosh, Platform-Specific Issues" for details.
7) Delete the Oberon/X application.
8) Delete the Oberon/F application. This application has the development system linked in. Therefore it is not permitted to distribute it!
9) Edit the About text in the System:Rsrc folder in an appropriate way.
10) Edit the menus text in the System:Rsrc folder in an appropriate way.
11) Delete everything else, except the Form, Host, Std, System, and Text folders with their respective Rsrc folders. Their other folders (Code, Docu, Sym) can be deleted! If you would delete also their Rsrc folders, the application would still operate (kind of), but lose all string mappings, all customized dialog layouts, and all custom menus.
How to Develop Oberon/F Components
This section gives an overview of the typical way how new Oberon/F components are developed. It summarizes the most important aspects of what has been said in the previous chapters.
In a first step, a subsystem name (-> Subsystems and Global Modules) for the project is chosen, and a suitable folder created (with its Code, Docu, Mod, Rsrc, and Sym folders). This folder must be in the Oberon/F folder itself, i.e. at the same location where the System, Host, etc. folders are. Note that there are no environment variables or path name lists in Oberon/F. File lookup is static and determined by module names, not by configurable search paths or similar constructs.
It is helpful to set up a text document which contains the names of all the subsystem's modules, starting with the one lowest in the module hierarchy. Such a tool text can be used as input to the Open
Module
List command. This command opens the source file of the module whose name is selected. This is convenient since it can much reduce the need to navigate through the folder hierarchy that would otherwise be necessary with the Open... command. As a mnemonic aid, the keyboard shortcut for Open
Module
List is the digit "0", while the keyboard shortcut of the Open... command is the letter "O". Open
Module
List is even more useful since it allows to open several files at the same time, if the selection includes several module names.
If you have preferred fonts or rulers for programming, you may want to set up a stationary pad. For that purpose, create a document with set up accordingly, save it under the stationary name, and then use the Finder's Get
Info command to turn the file into a stationary.
Now you are ready to create the module sources, which should be placed in your subsystem's Mod folder. In order to take advantage of autoindentation, you should use tab characters for indentation. You can directly compile the module on which you are working with the Compile command. This command compiles, but does not yet load, the module. The command Compile
Module
List takes a list of module names and compiles them all.
In order to load the module, you can execute one of its exported parameterless procedures, either by executing the Execute menu command on the command's name (e.g. on Dialog.Beep), or you can augment your tool text with commanders, e.g.
Dialog.Beep (call Insert
Commander). Once loaded, a module remains loaded, unless you explicitly unload it. Unloading can be done by calling Unload on the module source (working on the focus view, as does Compile), or by selecting a module name and calling Unload
Module
List (which also works on a sequence of module names, similar to Compile
Module
List). Note that modules must be unloaded from top to bottom, since only modules which are not imported anymore may be unloaded. To check this, you may call Loaded
Modules. For the unloading of such modules, there is a shortcut if you used commanders: option-click on the commander first unloads the old version of the module, then loads the new version, and then calls the procedure.
In order to get quick access to a module's definition or documentation, you can use the commands Interface (resp. Documentation). Interface calls the browser to construct a definition text out of a module's symbol file. Note that in this text you can select further module names (or names of imported constants, variables, types, or procedures) and get the interface of those by calling the same command again. If there is a documentation file available for a module, you can execute Documentation after selecting the module's name. This command opens the documentation text. If you have selected not only the module name (e.g. Views) but an object of this module (e.g. Views.Broadcast), the command tries to find the first occurence of the object's name which is written in boldface. The name is selected, and the window scrolls to the selection's position. In the rare cases where this first occurence is not the one you need, you may call Find
Again to search the next occurence.
In order to test a module, you can use module Out to write debugging output into the Log window. In order to set breakpoints, you can introduce HALT statements and recompile the module. The trap text which is opened when the HALT is reached gives you information about the call chain (stack) as it has been at the moment the command was interrupted. Note that at no point in time the normal Oberon/F environment is left, debugging takes place completely inside Oberon/F.
It is recommended to check preconditions and important invariants systematically in all programs, using the ASSERT statement. This debugging strategy is called static debugging, since error conditions are specified statically (even though they may be checked only at run-time). In an object-oriented environment, where the control flow tends to become too convoluted to follow step-by-step, the consequent application of assertions proves to keep debugging times shorter than any interactive debugging ever could.
Besides code, Oberon/F programs may also include resources. In the resource folder of a subsystem, there may be files for dialog layouts and for string mappings. Furthermore, there is a global menu configuration text. The latter can be opened with command Menus, edited, and then made the current configuration by calling Update
Menus. A menu item may not only have an action command, but also a guard command. Guards mainly determine whether a menu item is currently enabled or disables. If a guard cannot be executed (e.g. because its module cannot be loaded), a "?" appears in front of the item's name, and the item is disabled. It is never attempted again to execute the guard command, unless explicitly requested, by calling Flush
Resources. The same command also flushes an internal cache of string mappings, i.e. it should also be called after a strings resource file has been changed.
Dialogs are linked to global program variables. A new dialog is created by typing in the variable's name in the New
From dialog. The new dialog has a default layout, which can be modified interactively. Then the dialog should be stored, using the variable's name as file name (e.g. find for variable TextCmds.find) in the subsystem's resource folder. The properties of a dialog element (a control) can be inspected and modified using the Control
Properties command.
Distribution of an Oberon/F component simply consists of distributing its subsystem folder. Installation simply consists of copying a subsystem folder into the Oberon/F folder. If it is desired to link one or several subsystems together with an Oberon/F core, a linker can be used (-> Oberon/F, Macintosh, Platform-Specific Issues).
Standard Commands
In this section, the menu items of the standard menus File, Edit, Font, Attributes, and Windows are described. For a menu item which is not permanently enabled, the condition for enabling it is specified.
File Menu
Opens a new document window containing an empty text view.
Open...
Opens a modal file selection dialog. Only Oberon/F documents are shown (i.e. Macintosh files with file type = "oODC"). If the option key was held down while clicking on the menu bar, Open Any... appears. This command behaves the same way as Open..., except that all files are shown in the standard file dialog, regardless of their types.
Close
Enabled: front window
Closes the front window. If the window is a primary document window and its contents has been modified ("dirty"), the user is asked whether to save the window's contents in a file.
Enabled: dirty front document window
Saves the front window's contents to a file. If the window's contents has not yet been saved to a file, the user is asked for a file name.
Save As
Enabled: front window
Saves the front window's contents to a file. The user is always asked for a file name.
Page Setup...
Enabled: front window
Asks the user for the page information of the front window's document, for later printing.
In addition to the data which is specific to the current printer driver, the margins can be set (the distances between the paper's edges and the printed area), and a standard header can be switched on or off. The standard header consists of a page number and a date.
Note: when using LaserWriter 7.x.y drivers, you should switch on greyscale printing (not black/white), otherwise printing may produce entirely black pages. If possible, switch to LaserWriter 8.x.y drivers, which don't have this bug.
Print...
Enabled: front window
Asks the user for printing information, and then creates a print-out accordingly.
Print Selection...
Enabled: singleton in front window
Asks the user for printing information, and then creates a print-out accordingly. Only the selection is printed. This command corresponds to the sequence Copy/Paste To New Window/Print...
Terminates the application. If windows with modified contents are open, the user is asked whether to save them in files.
Edit Menu
Undo [...]
Enabled: non-empty undo stack of operations
Reverses the effect of the most recent modifying operation. Usually, the kind of operation is given behind the word "Undo", e.g. Undo
Paste.
Redo [...]
Enabled: non-empty redo stack of operations
Restores the effect of the most recently undone operation. Usually, the kind of operation is given behind the word "Redo", e.g. Redo
Paste.
Enabled: selection in focus view in front window
Deletes the selection and puts a copy into the clipboard.
Enabled: selection in focus view in front window
Puts a copy of the selection into the clipboard.
Paste
Enabled: caret in focus view in front window, non-empty clipboard
Pastes a copy of the clipboard's contents at the caret position. If the focus view contains the same kind of data as the clipboard, the data is inserted directly into the focus view's data. Otherwise, and if the focus view is a container, a copy of the whole view containing the clipboard data is inserted into the focus view's data.
Clear
Enabled: selection in focus view in front window
Deletes the selection, without putting it into the clipboard.
Paste Object
Enabled: caret in focus view in front window, non-empty clipboard
Pastes a copy of the clipboard's contents at the caret position. If the focus view is a container, a copy of the whole view containing the clipboard data is inserted into the focus view's data.
Paste To New Windows
Enabled: non-empty clipboard
Opens a copy of the clipboard's contents into a new document window.
Select Document
Enabled: front window
Selects the root view of the front window's document as a singleton. Note the difference to Select
All, which selects the latter's contents instead (or rather the contents of whatever view is currently the focus).
Select All
Enabled: selectable focus view in front window
Selects the whole focus view's contents.
Font Menu
Available: font-carrying selection or caret in focus view in front window
This menu lists all the fonts which are currently available. The menu item for the caret's font, or the font of the selection if it is homogeneous, is checked.
Attributes Menu
Available: style/size/color-carrying selection or caret in focus view in front window
The following commands work on the selection; if there is no selection, the caret's current attributes are affected instead. These attributes are used as defaults when typing in new text.
For colors, there is a system-wide color (default color) which can be modified by the user. Everything drawn in this color will be updated accordingly.
Plain
Enabled: style-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is plain, or if selection is homogeneously plain (i.e. non-bold, non-italicized, non-underlined, and non-striked-out)
Removes all style attributes (bold, italic, underline, strikeout) from the selection.
Enabled: style-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is bold, or if selection is homogeneously bold.
If the selection is homogeneously bold, it is made non-bold, otherwise it is made bold.
Italic
Enabled: style-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is italic, or if selection is homogeneously italic.
If the selection is homogeneously italic, it is made non-italic, otherwise it is made italic.
Underline
Enabled: style-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is underlined, or if selection is homogeneously underlined.
If the selection is homogeneously underlined, it is made non-underlined, otherwise it is made underlined.
Strikeout
Enabled: style-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is striked out, or if selection is homogeneously striked out.
If the selection is homogeneously striked out, it is made non-striked-out, otherwise it is made striked out.
9 point, 10, 12, 16, 20, 24
Enabled: size-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret has the given size, or if the selection is homogeneously of the given size
The selection is set to the given point size.
Other Size...
Enabled: size-carrying selection or caret in focus view in front window
Checked: if none of the other sizes apply
A tool dialog is opened, which allows to enter a particular font size in points, and then to set the selection to this size.
Default
Enabled: color-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret has the default color, or if the selection is homogeneously of the default color
Sets the selection's color to the default color.
Black
Enabled: color-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is black, or if the selection is homogeneously black
Sets the selection's color to black.
Enabled: color-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is red, or if the selection is homogeneously red
Sets the selection's color to red.
Green
Enabled: color-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is green, or if the selection is homogeneously green
Sets the selection's color to green.
Enabled: color-carrying selection or caret in focus view in front window
Checked: if text to the left and to the right of the caret is blue, or if the selection is homogeneously blue
Sets the selection's color to blue.
Other Color...
Enabled: color-carrying selection or caret in focus view in front window
Checked: if none of the other colors apply
Asks the user for a color, to which it then sets the selection.
Set Default...
Enabled: color-carrying selection or caret in focus view in front window
Asks the user for a color, to which it then sets the default color.
Windows Menu
New Window
Enabled: front window
Opens a new window on the same document as the front window. The window is of the same kind as the front window. The window's title is put between "(" and ")" parentheses.
Open As Window
Enabled: focus view in front window, document in front window is not viewer
Opens a new window on the front window's focus view. The window is an auxiliary window. The window's title is put between "(" and ")" parentheses.
Tile Horizontal
Arrange windows from left to right in a non-overlapping fashion. This command does not affect non-resizable windows, and it ignores some windows when there are too many open windows for a reasonable tiling. The front window becomes the left-most window.
Tile Vertical
Arrange windows from top to bottom in a non-overlapping fashion. This command does not affect non-resizable windows, and it ignores some windows when there are too many open windows for a reasonable tiling. The front window becomes the top-most window.
Stack
Arrange windows on top of each other. This command does not affect non-resizable windows, and it ignores some windows when there are too many open windows for a reasonable stacking. The front window remains front window.
Show Clipboard / Hide Clipboard
If the clipboard is open, it closes it and all its secondary windows. Otherwise it opens a clipboard window.
windows
Here the list of open windows is appended, the front window at the top (checked). Document window titles are in boldface if their contents has been modified.
Custom Commands
The other menus can be configured freely with commands of your choice. The configuration file resides in the folder System:Rsrc under the name menus (-> "Menu Configuration"). In this text, you can assemble the commands of your choice. For distribution purposes however, you may not use any of the Dev subsystem's commands.
Instead of describing the default menu configuration for development purposes, a list of all available commands is given here, sorted by the modules which provide these commands.
Commands which don't appear in the list below are private, and only used internally.
Controls
Controls are special views which usually appear in dialogs: buttons, checkboxes, etc. In Oberon/F, buttons are typically linked to fields of a record variable. Exceptions are "simple" buttons which directly contain an Oberon command as their link. Use DevInspector to inspect and modify the properties of a control.
CloseDialog
This procedure only works as command in a simple push button. It closes the window in which the push button appears.
DepositCancelButton
Deposits a cancel button. Cancel buttons react to escape characters. They are simple push buttons which call Controls.CloseDialog.
DepositCaption
Deposits a caption, i.e. a text message which cannot be edited.
DepositCheckBox
Deposits a check box.
DepositField
Deposits a field for editable text.
DepositPushButton
Deposits a push button.
DepositRadioButton
Deposits a radio button.
DevAlienTool
Alien views are views which, for some reason, cannot be loaded correctly. The reason may be a programming error, e.g. a different number of bytes is read than was written, or it may be a version problem (an unknown version was detected). Usually however, the problem is that some code for the view cannot be loaded, because it is missing or inconsistent. The alien tool helps to analyze such problems.
Analyze
Guard: DevAlienTool.SingletonGuard
This command analyzes the singleton alien view, and opens a window with the textual analysis.
SingletonGuard
This guard disables the current menu item if the current front singleton isn't an alien view.
DevBrowser
ShowInterface
Guard: SelectionGuard
If a module name is selected, this command shows the complete definition of the module. If a qualident is selected, only the definition of the corresponding item is shown.
DevCmds
log: RECORD (Dialog.Interactor)
alerts, reports: BOOLEAN;
Set: PROCEDURE
This is the interactor for the Log
Settings dialog. alerts determines whether messages created with the DevLog routines (or Out) are written to the log or presented in dialogs. reports determines whether error messages issued during the internalization of a store should be presented to the user or not.
ClearLog
Clears the log text.
FlushResources
Flush menu guard and string translation resources.
InitLogDialog
Initialization command for the Log
Settings dialog.
OpenLog
Opens a log window if none is open, otherwise it brings the log window to the top.
OpenModuleList
Guard: TextCmds.SelectionGuard
Opens the modules whose names are selected.
DevCommanders
Deposit
Deposit command for commanders.
DevCompiler
Compile
Guard: TextCmds.FocusGuard
Compile the module whose source is in the focus view.
CompileList
Guard: TextCmds.SelectionGuard
Compile the list of modules whose names are selected. When the first error is detected, the offending source is opened to show the error.
CompileSelection
Guard: TextCmds.SelectionGuard
Compile the module, whose beginning is selected.
DevDebug
Execute
Guard: TextCmds.SelectionGuard
Execute the string (between quotation marks), which must have the form of an Oberon command sequence, e.g. "Dialog.Beep; Dialog.Beep". For simple commands, the string delimiters may be omitted, e.g. Dialog.Beep.
ShowCommands
Guard: TextCmds.SelectionGuard
Show the commands (parameterless exported procedures) of the module whose name is selected.
ShowGlobalVariables
Guard: TextCmds.SelectionGuard
Show the global variables (parameterless exported procedures) of the module whose name is selected.
ShowLoadedModules
Show the list of all loaded modules.
ShowLoadedTopModules
Show the list of loaded top modules, i.e. of modules which are not imported by other modules. This command can be convenient to determine the modules which should be linked together when building an application (all depending modules are linked in automatically).
ShowResources
Show the current use of resources such as heap space and open file access paths.
Unload
Guard: TextCmds.FocusGuard
Tries to unload the module whose source is in the focus view. Unloading fails if the specified module is not loaded yet, or if it is not a top module.
UnloadModules
Guard: TextCmds.SelectionGuard
Tries to unload a list of modules whose names are selected. Unloading may partially or completely fail if one of the specified modules is not loaded yet, or if it is still being importet by at least one client module. Modules must be unloaded from top to bottom.
DevMarkers
NextError
Guard: TextCmds.FocusGuard
Move caret forward after the next error marker. If there is none, the text is scrolled to the beginning.
ToggleCurrent
Guard: TextCmds.FocusGuard
Toggle the state of the marker before the caret.
UnmarkErrors
Guard: TextCmds.FocusGuard
Removes all error markers.
DevInspector
The inspector makes it possible to inspect and modify properties of a control. Currently five types of controls are supported: push buttons, check boxes, radio buttons, and text fields.
inspect: RECORD (Dialog.Interactor)
control-: Dialog.String;
label: ARRAY 40 OF CHAR;
link, guard: Dialog.String;
element, default, cancel: BOOLEAN;
level: INTEGER;
lightFont: BOOLEAN;
GetNext, Set: PROCEDURE
This is the interactor for the Control
Properties dialog. It presents the various control properties of a singleton.
FormCmds
AlignBottom
Guard: FormCmds.SelectionGuard
Move all selected views such that their bottom sides are aligned to the bottommost view in the selection.
AlignLeft
Guard: FormCmds.SelectionGuard
Move all selected views such that their left sides are aligned to the leftmost view in the selection.
AlignRight
Guard: FormCmds.SelectionGuard
Move all selected views such that their right sides are aligned to the rightmost view in the selection.
AlignToColumn
Guard: FormCmds.SelectionGuard
Move all selected views such that their horizontal centers become aligned vertically.
AlignToRow
Guard: FormCmds.SelectionGuard
Move all selected views such that their vertical centers become aligned horizontally.
AlignTop
Guard: FormCmds.SelectionGuard
Move all selected views such that their top sides are aligned to the topmost view in the selection.
DuplicateView
Guard: FormCmds.SingletonGuard
This command makes a copy of the current front focus singleton, and inserts it close the the original.
FocusGuard
This guard disables the current menu item if the current front focus isn't a form view.
ForceToGrid
Guard: FormCmds.FocusGuard
Moves all views in the focus form such that their top-left corners come to lie on the grid.
SelectOffGridViews
Guard: FormCmds.FocusGuard
Selects all views in the focus form whose top-left corners don't lie on the grid.
SelectionGuard
This guard disables the current menu item if the current front focus isn't a form view, or if it doesn't contain a selection
SingletonGuard
This guard disables the current menu item if the current front focus isn't a form view, or if it doesn't contain a singleton.
HostCmds
VAR allocator: Dialog.String
This string containers the allocation command executed when New is invoked. By default, it is set to"TextViews.Deposit; Open".
size: RECORD (Dialog.Interactor)
size: LONGINT;
Set: PROCEDURE
This is the interactor for the Other
Size dialog.
ContainerGuard
This guard disables the current menu item if the current focus is not a container view.
RecalcFocusSize
Lets the current focus recalculate its preferred size and asks the container of the focus to accept this size, if possible.
ToggleNoFocusGuard
This guard disables the current menu item if the focus cannot be toggled between editor and layout mode.
ToggleNoFocus
Toggles the focus between editor and layout mode.
StdClocks
Deposit
Deposit command for standard clocks.
StdControlCmds
MakeField
Guard: SingletonGuard
Tries to change the singleton into a field control. This works on radio buttons.
MakePushButton
Guard: SingletonGuard
Tries to change the singleton into a push button control.
MakeRadioButton
Guard: SingletonGuard
Tries to change the singleton into a radio button control. This works on number fields.
MakeCaption
Guard: SingletonGuard
Tries to change the singleton into a caption. This works on text fields.
SetCancelButton
Guard: ContainerGuard
Cancel buttons react on the input of escape characters. This command removes the cancel property from the current cancel button in the focus container, if there is one. If a singleton push button is selected, it then sets this button's cancel property.
SetDefaultButton
Guard: ContainerGuard
Default buttons react on the input of carriage
return and enter characters. This command removes the default property from the current default button in the focus container, if there is one. If a singleton push button is selected, it then sets this button's default property.
StdMenuTool
UpdateMenus
Guard: TextCmds.FocusGuard
This command takes the focus text and interprets it as a menu configuration. If it contains syntax errors, the error is selected, otherwise the current menu configuration is updated appropriately.
Replace dialog. It allows to specify several options: ignoreCase makes searching insensitive to case, wordBeginsWith restricts searching to the beginning of words, and wordEndsWith restricts searching to the end of words. wordBeginsWith and wordEndsWith together restrict searching to whole words.
FindAgain
Guard: TextCmds.FindAgainGuard
This command searches for the currently selected text string, starting from the end of the selection. If there is no selection, it searches for the most recently used search string of Find and FindAgain, starting from the caret position.
FindAgainGuard
This guard disables the current menu item if there is no current text selection, and if no string was searched previously, with Find or FindAgain.
FocusGuard
This guard disables the current menu item if the current focus is not a text view.
InitFindDialog
This initialization command sets up the TextCmds.find interactor with the current text selection.
InsertDigitSpace
Guard: PasteCharGuard
Pastes a digit space, i.e. a space which has the same width as a digit. Whether a digit space has this defined width depends on the font used; some fonts have digits of varying widths.
InsertNBHyphen
Guard: PasteCharGuard
Pastes a non-breaking hyphen.
InsertNBSpace
Guard: PasteCharGuard
Pastes a non-breaking space, i.e. a space which cannot be used to break a word.
InsertParagraph
Guard: PasteCharGuard
Pastes a paragraph character.
InsertRuler
Guard: PasteViewGuard
Pastes a new ruler, which is set up the same way as the ruler in the same text closest above. If there is no ruler above, the values of the default ruler are taken.
InsertSoftHyphen
Guard: PasteCharGuard
Pastes a soft hyphen, i.e. a hyphen which only becomes visible if it is used to break a word.
ListAlienViews
Guard: TextCmds.FocusGuard
Opens a text containing the list of alien views contained in this text.
MakeDefaultAttributes
Guard: TextCmds.SelectionGuard
Sets the focus text's default attributes to the ones of the current selection in this text.
MakeDefaultRuler
Guard: SingletonGuard
Sets the focus text's default ruler values to the ones of the currently selected ruler in this text.
SelectionGuard
This guard disables the current menu item if the current focus is not a text view or doesn't contain a selection.
ShiftLeft
Guard: TextCmds.SelectionGuard
This command removes one tab character from the white space at the beginning of each line spanned by the current selection.
ShiftRight
Guard: TextCmds.SelectionGuard
This command inserts one tab character from the white space at the beginning of each line spanned by the current selection.
Subscript
Guard: TextCmds.SelectionGuard
This command moves the selected text up vertically, into a superscript position.
Superscript
Guard: TextCmds.SelectionGuard
This command moves the selected text down vertically, into a subscript position.
ToggleMarks
Guard: TextCmds.ToggleMarksGuard
This command makes text rulers and paragraph characters visible if they aren't, and hides them if they are.
ToggleMarksGuard
This guard disables the current menu item if the current focus isn't a text view. Furthermore it sets up the correct string of the item (Show